/**
 * @file interfacefifo.c
 * @brief Implementa le funzioni per realizzare un'interfaccia con dei file fifo.
 *
 * Vengono realizzare le funzioni per creare/avviare/chiudere una comunicazione fifo
 * e infine per leggere e scrivere sulla fifo.
 *
 * @date Mar 10, 2012
 * @author Francesco Corvino
 */
#include "interfacefifo.h"

/**
 * @brief Prova a creare una fifo secondo il nome passato.
 *
 * @param name percorso dove creare la fifo.
 * @return 1 se è stata effettuata la creazione della fifo, 0 se era già presente, -1 se il processo è fallito.
 */
int InterfaceFifo_createFifo(char * name){
    if (access(name, F_OK) == -1) {
        int res = mkfifo(name, 0777);
        if (res != 0) return -1;
        else return 1;
    } else return 0;
}

void InterfaceFifo_startComm(InterfaceFifo * fifo){
    fifo->pipefd = open(fifo->name, fifo->openmode);
    // set status of pipe
    if (fifo->pipefd != -1) fifo->status = 1;
    else fifo->status = -1;
}

void InterfaceFifo_closeComm(InterfaceFifo * fifo){
    if(fifo->status) close(fifo->pipefd);
}


/**
 * @brief Metodo delegato della funzione read().
 *
 * @param fifo puntatore della difo da cui leggere.
 * @param buffer puntatore dove allocare i bytes letti.
 * @param maxdim dimensione massima della memoria da allocare.
 * @return numero di byte effettivamente letti.
 */
int InterfaceFifo_rcvMsg(InterfaceFifo * fifo,char * buffer,int maxdim){
	return read(fifo->pipefd,buffer,maxdim);
}

/**
 * @brief Metodo delegato della funzione write().
 *
 * @param fifo puntatore della fifo su cui scrivere.
 * @param buffer puntatore alla stringa da scrivere.
 * @return numero di byte effettivamente scritti.
 */
int InterfaceFifo_sendMsg(InterfaceFifo * fifo,char * buffer){
	return write(fifo->pipefd,buffer,strlen(buffer));
}


/**
 * @brief Inizializza un oggetto settandono opportumanente i valori.
 *
 * @param obj Oggetto da inizializzare.
 * @param pid Process Identificator con il quale aprire la sessione.
 * @param pathToDir Percorso alla directory dove bisogna aprire le fifo.
 * @param versus Specifica se è una fifo verso il client o verso il server
 */
void ParamsComm_Init(ParamsComm * obj, int pid, char* pathToDir ,int versus){
	if(versus == FIFO_CLIENT){ // comunicazione verso il client
		// ricava i nomi dei file dove creare la fifo
		sprintf(obj->infifo.name, FILENAME_FIFOIN, pathToDir, pid);
		sprintf(obj->outfifo.name, FILENAME_FIFOOUT, pathToDir, pid);
	} else { // comunicazione verso il server
		// ricava i nomi dei file dove creare la fifo
		sprintf(obj->infifo.name, FILENAME_FIFOOUT, pathToDir, pid);
		sprintf(obj->outfifo.name, FILENAME_FIFOIN, pathToDir, pid);
	}
}


/**
 * @brief Avvia la comunicazione creando le due fifo aprendone il file.
 *
 * @param obj Oggetto con i dati sulle comunicazioni da avviare.
 * @return 1 se le operazioni hanno avuto successo, -1 altrimenti
 */
int ParamsComm_Start(ParamsComm *obj){
	// crea 2 fifo
	obj->infifo.openmode = O_RDWR;//ONLY;

	obj->outfifo.openmode = O_RDWR;//ONLY;

	// creazione delle fifo
	if(InterfaceFifo_createFifo(obj->infifo.name)==-1){
		return -1;
	}
	if(InterfaceFifo_createFifo(obj->outfifo.name)==-1){
		return -1;
	}

	// apertura delle fifo
	InterfaceFifo_startComm(&(obj->outfifo));
	InterfaceFifo_startComm(&(obj->infifo));
	return 1;
}

/**
 * @brief Termina una comunicazione chiudendo i due canali FIFO.
 * @param obj Oggetto contenente i dati sui canali.
 */
void ParamsComm_Close(ParamsComm * obj){
	InterfaceFifo_closeComm(&(obj->infifo));
	InterfaceFifo_closeComm(&(obj->outfifo));
}

/**
 * @brief Funzione che permette di registrare una sessione.
 *
 * @param applicationDir
 */
void registerSession(char* applicationDir){
	char registrationMsg[255];
	pid_t mypid = getpid();
	sprintf(registrationMsg,"%s %d ", NEWSESSION_STR, mypid);

	InterfaceFifo regFifo;
	sprintf(regFifo.name,"%s/%s",
			applicationDir,FILENAME_FIFOLISTENER);
	regFifo.openmode = O_WRONLY;

	InterfaceFifo_createFifo(regFifo.name);

	InterfaceFifo_startComm(&regFifo);

	InterfaceFifo_sendMsg(&regFifo,registrationMsg);

	InterfaceFifo_closeComm(&regFifo);
}

